package com.bobo.mm;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.bobo.mm.socket.SocketService;

/**
 * 统一入口
 * Created by cocolove2 on 2018/5/29.
 */
public final class CSocket {
    private static final String TAG = "CSocket";
    private IService mService;
    private Context mContext;
    private OnServiceListener mServiceListener;

    private CSocket() {
    }

    private static class MClientHolder {
        @SuppressLint("StaticFieldLeak")
        private static final CSocket Instance = new CSocket();
    }

    public static CSocket getInstance() {
        return MClientHolder.Instance;
    }

    /**
     * 通信服务绑定连接
     */
    private ServiceConnection mConnection;

    private void initConnection() {
        mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mService = IService.Stub.asInterface(service);
                if (mServiceListener != null) {
                    if (mService == null) {
                        Log.e(TAG, "Service 连接失败");
                        mServiceListener.onBindError();
                    } else {
                        mServiceListener.onBindSuccess();
                    }
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.e(TAG, "Service has unexpectedly disconnected");
                mService = null;
                if (mServiceListener != null) {
                    mServiceListener.onUnBind();
                }
            }
        };
    }

    /**
     * 初始化socket客户端
     *
     * @param context 上下文
     */
    public void init(Context context, OnServiceListener listener) {
        initConnection();
        mContext = context.getApplicationContext();
        mServiceListener = listener;
        Intent intent = new Intent(mContext, SocketService.class);
        intent.setAction(SocketService.class.getName() + ".action.start");
        mContext.startService(intent);
        intent.setAction(SocketService.class.getName() + ".action.bind");
        mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    /**
     * 启动socket
     *
     * @param config   socket配置
     * @param listener 状态回调监听
     */
    public void start(ClientConfig config, final OnCSocketListener listener) {
        if (mService != null) {
            try {
                mService.start(config, new ISocketListener.Stub() {
                    @Override
                    public void onOpen(String channelId, byte[] response) throws RemoteException {
                        if (listener != null) {
                            listener.onOpen(channelId, response);
                        }
                    }

                    @Override
                    public void onByteMessage(String channelId, byte[] message) throws RemoteException {
                        if (listener != null) {
                            listener.onMessage(channelId, message);
                        }
                    }

                    @Override
                    public void onTextMessage(String channelId, String message) throws RemoteException {
                        if (listener != null) {
                            listener.onMessage(channelId, message);
                        }
                    }

                    @Override
                    public void onClosing(String channelId, int code, String msg) throws RemoteException {
                        if (listener != null) {
                            listener.onClosing(channelId, code, msg);
                        }
                    }

                    @Override
                    public void onClosed(String channelId, int code, String msg) throws RemoteException {
                        if (listener != null) {
                            listener.onClosed(channelId, code, msg);
                        }
                    }

                    @Override
                    public void onFailure(String channelId, String exceptionClass, String msg) throws RemoteException {
                        if (listener != null) {
                            listener.onFailure(channelId, exceptionClass, msg);
                        }
                    }

                    @Override
                    public void onReconnecting(String channelId, int count) throws RemoteException {
                        if (listener != null) {
                            listener.onReconnecting(channelId, count);
                        }
                    }
                });
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送消息
     *
     * @param message 消息内容
     */
    public boolean sendMessage(String channelId, byte[] message) {
        try {
            if (mService != null) {
                return mService.sendByteMessage(channelId, message);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean sendMessage(String channelId, String message) {
        try {
            if (mService != null) {
                return mService.sendTextMessage(channelId, message);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 释放socket资源，停止socket服务
     */
    public void release() {
        try {
            if (mConnection != null) {
                mContext.unbindService(mConnection);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            mConnection = null;
            mService = null;
        }
        mContext.stopService(new Intent(mContext, SocketService.class));
    }

    public interface OnServiceListener {
        void onBindSuccess();

        void onBindError();

        void onUnBind();
    }
}
